/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

package checker

import (
	"errors"
	"fmt"
	"time"

	"hundsun.com/hsl/hschain/consensus/types"

	"hundsun.com/hsl/hschain/common/util/pb"
	"hundsun.com/hsl/hschain/protos"
	pbledger "hundsun.com/hsl/hschain/protos/ledger"
)

// Checker 拉取块并负责验证
type Checker struct {
	module *RaftChecker
}

// Init 初始化
func (ck *Checker) Init(conf *types.CheckerConfig) error {
	conf.BlockCreatorValidator = ck.createBlockCreatorValidator()
	return ck.module.baseclient.InitChecker(conf)
}

func (ck *Checker) createBlockCreatorValidator() types.BlockCreatorValidator {
	return func(blk *pbledger.Block) (err error) {
		log := pb.GetBlockLog(ck.module.log, blk)
		start := time.Now()
		err = validateBlockCreator(blk)
		log.WithCostField(start).Debug("block validated")
		if err != nil {
			return err
		}

		return nil
	}
}

// validateBlockCreator 验证区块创建者是否是创世块中配置的，背书签名是否正确
func validateBlockCreator(block *pbledger.Block) error {
	//1.校验区块签名基本格式
	if block.Header.Signature == nil || len(block.Header.Signature.Signature) == 0 || len(block.Header.Signature.PublicKey) == 0 {
		return errors.New("signature content format error")
	}

	//2.校验块签名
	blockCreator := block.Header.Signature.GetAddress()
	checked := false
	for _, miner := range defaultMiners {
		if blockCreator == protos.Address(miner.Address) {
			checked = true
		}
	}
	if !checked {
		return fmt.Errorf("invalid creator '%s' of block[%d]", blockCreator, block.Header.Number)
	}
	if !block.Verify() {
		return fmt.Errorf("failed to verify signature fo block '%d'", block.Header.Number)
	}
	return nil
}
